##########################################
## Copyright 2012-2013 Ceruti Francesco & contributors
##
## This file is part of LiSP (Linux Show Player).
##########################################

from PyQt4 import QtCore, QtGui
from lisp.core.plugin import Plugin
from lisp.core.media import Media


class Scenes(Plugin):

    PLUGIN_NAME = 'Scenes'

    def __init__(self, main):
        self.mainWindow = main.mainWindow
        self.collector = main.collector

        self.scenes = []

        # Voice in mainWindow menu under 'edit'
        self.mainWindow.menuEdit.addSeparator()

        self.actionScenes = QtGui.QAction(self.mainWindow, triggered=self.scenesUi)
        self.actionScenes.setText("Scenes edit")
        self.mainWindow.menuEdit.addAction(self.actionScenes)

    def scenesUi(self):
        self.sUi = ScenesUi(self.scenes, self.collector)
        self.sUi.exec_()

    def reset(self):
        for sc in self.scenes:
            sc.disconnect()
        self.scenes = []

    def getData(self):
        conf = {}
        for scene in self.scenes:
            conf[scene.name] = []
            for media in scene.sequence:
                conf[scene.name].append(media.uuid)
        return conf

    def setData(self, conf):
        for key in conf:
            medialist = []
            for uuid in conf[key]:
                for media in self.collector.media:
                    if(media.uuid == uuid):
                        medialist.append(media)
                        break
            if(len(medialist) > 0):
                self.scenes.append(Scene(medialist, key))


class ScenesUi(QtGui.QDialog):

    def __init__(self, scenes, collector, parent=None):
        super(ScenesUi, self).__init__(parent)

        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setMaximumSize(542, 300)
        self.setMinimumSize(542, 300)
        self.resize(542, 300)

        self.media_list = collector.media
        self.scenes = scenes

        self.pushButton = QtGui.QPushButton(self)
        self.pushButton.setGeometry(QtCore.QRect(420, 10, 111, 31))

        self.pushButton_2 = QtGui.QPushButton(self)
        self.pushButton_2.setGeometry(QtCore.QRect(420, 50, 111, 31))

        self.pushButton_3 = QtGui.QPushButton(self)
        self.pushButton_3.setGeometry(QtCore.QRect(420, 90, 111, 31))

        self.pushButton_5 = QtGui.QPushButton(self)
        self.pushButton_5.setGeometry(QtCore.QRect(420, 190, 111, 31))

        self.listWidget = QtGui.QListWidget(self)
        self.listWidget.setGeometry(QtCore.QRect(10, 10, 401, 281))
        self.listWidget.doubleClicked.connect(self.renameSelctedScene)

        for scene in self.scenes:
            widget = QtGui.QListWidgetItem()
            widget.setText(scene.name)
            self.listWidget.addItem(widget)

        self.retranslateUi()

        self.pushButton.clicked.connect(self.addScene)
        self.pushButton_2.clicked.connect(self.removeScene)
        self.pushButton_3.clicked.connect(self.modifyScene)
        self.pushButton_5.clicked.connect(self.accept)

    def retranslateUi(self):
        self.setWindowTitle("Scenes edit")
        self.pushButton.setText("Add scene")
        self.pushButton_2.setText("Remove")
        self.pushButton_3.setText("Modify")
        self.pushButton_5.setText("Ok")

    def addScene(self):
        if(len(self.media_list) > 0):
            selectUi = SelectionDialog(self, self.media_list, [])
            selectUi.exec_()

            if(selectUi.result() == QtGui.QDialog.Accepted):
                if(len(selectUi.selected) > 0):
                    scene = Scene(selectUi.selected)
                    self.scenes.append(scene)

                    widget = QtGui.QListWidgetItem()
                    self.listWidget.addItem(widget)
                    while not self.renameScene(widget):
                        pass
                else:
                    QtGui.QMessageBox.warning(self, 'Error', 'No media selected!')
        else:
            QtGui.QMessageBox.warning(self, 'Error', 'No media found in program!')

    def removeScene(self):
        if(len(self.listWidget.selectedIndexes()) != 0):
            self.scenes[self.listWidget.selectedIndexes()[0].row()].disconnect()
            self.scenes.pop(self.listWidget.selectedIndexes()[0].row())
            self.listWidget.takeItem(self.listWidget.selectedIndexes()[0].row())

    def modifyScene(self):
        if(len(self.listWidget.selectedIndexes()) != 0):
            scene = self.listWidget.selectedIndexes()[0].row()
            selectUi = SelectionDialog(self, self.media_list,
                                       self.scenes[scene].sequence)
            selectUi.exec_()

            if(selectUi.result() == QtGui.QDialog.Accepted):
                if(len(selectUi.selected) > 0):
                    self.scenes[scene].disconnect()
                    self.scenes[scene] = Scene(selectUi.selected)
                    while not self.renameSelctedScene():
                        pass
                else:
                    QtGui.QMessageBox.warning(self, 'Error', 'No media selected!')

    def renameSelctedScene(self):
        if(len(self.listWidget.selectedIndexes()) != 0):
            return self.renameScene(self.listWidget.selectedItems()[0])
        return False

    def renameScene(self, scene):
        name = QtGui.QInputDialog.getText(self, 'Input', 'Name: ', text=scene.text())
        if(name[1]):
            for sc in self.scenes:
                if(name[0] == sc.name):
                    QtGui.QMessageBox.critical(self, 'Error', 'Name already in use!')
                    return False
            scene.setText(name[0])
            self.scenes[self.listWidget.indexFromItem(scene).row()].name = name[0]
            return True
        return False


class SelectionDialog(QtGui.QDialog):

    def __init__(self, parent, media_list, selected):
        super(SelectionDialog, self).__init__(parent)

        self.setWindowTitle("Traces select")
        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setMaximumSize(600, 275)
        self.setMinimumSize(600, 275)
        self.resize(600, 275)

        self.media_list = media_list
        self.selected = selected

        self.buttonBox = QtGui.QDialogButtonBox(self)
        self.buttonBox.setGeometry(400, 240, 180, 32)
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok)

        self.listWidget_all = QtGui.QListWidget(self)
        self.listWidget_all.setGeometry(5, 10, 290, 220)
        self.listWidget_all.itemDoubleClicked.connect(self.itemAdded)
        self.listWidget_all.setDragEnabled(True)

        self.listWidget_sel = QtGui.QListWidget(self)
        self.listWidget_sel.setGeometry(305, 10, 290, 220)
        self.listWidget_sel.itemDoubleClicked.connect(self.itemRemoved)
        self.listWidget_sel.setDragEnabled(True)
        self.listWidget_sel.setDragDropMode(QtGui.QAbstractItemView.DragDrop)

        self.help = QtGui.QPushButton(self)
        self.help.setIcon(QtGui.QIcon.fromTheme('help-contents'))
        self.help.setGeometry(5, 235, 36, 36)
        self.help.setToolTip('How to')

        self.help.clicked.connect(self.helpMessage)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.readList()

    def helpMessage(self):
        QtGui.QMessageBox.information(self, 'Help',
                                      '<b>Add</b>: double click (left side)<br>'
                                      '<b>Add</b>: drag & drop (from left to right)<br>'
                                      '<b>Remove</b>: double click (right side)<br>'
                                      '<b>Move</b>: drag & drop (right side)')

    def readList(self):
        for media in self.media_list:
            if(media.state != Media.NONE):
                widget = QtGui.QListWidgetItem()
                widget.setText('pos: ' + str(media.conf['pos']) +
                               ' - ' + media.conf['name'])
                widget.setData(QtCore.Qt.UserRole,
                               self.media_list.index(media))
                self.listWidget_all.addItem(widget)

                if(media in self.selected):
                    self.listWidget_sel.addItem(QtGui.QListWidgetItem(widget))

    def itemAdded(self, widget):
        self.listWidget_sel.addItem(QtGui.QListWidgetItem(widget))

    def itemRemoved(self, widget):
        self.listWidget_sel.takeItem(self.listWidget_sel.indexFromItem(widget).row())

    def accept(self):
        self.selected = []
        for i in range(self.listWidget_sel.count()):
            media = self.listWidget_sel.item(i).data(QtCore.Qt.UserRole)
            self.selected.append(self.media_list[media])
        super().accept()


class Scene:

    def __init__(self, medialist, name=''):
        self.sequence = medialist
        self.name = name
        self.proxy = lambda t: self.next()

        self.setCurrent(0)

    def next(self):
        self.disconnect()

        if(self.current == len(self.sequence) - 1):
            self.setCurrent(0)
        else:
            self.setCurrent(self.current + 1)
            self.sequence[self.current].play()

    def disconnect(self):
        try:
            self.sequence[self.current].onEndOfStream.disconnect(self.proxy)
        except Exception:
            pass

    def setCurrent(self, index):
        self.current = index
        self.sequence[index].onEndOfStream.connect(self.proxy)
